/*
 * Project Beknyou
 * Copyright (c) 2010-2011 Saint Paul College, All Rights Reserved
 * Redistributions in source code form must reproduce the above
 * Copyright and this condition.
 * The contents of this file are subject to the GNU General Public
 * License, Version 2 (the "License"); you may not use this file
 * except in compliance with the License. A copy of the License is
 * available at http://www.opensource.org/licenses/gpl-license.php.
 */
package com.benkyou.client.network;

import com.jme3.network.Client;
import com.jme3.network.Message;
import com.jme3.network.MessageListener;
import com.benkyou.client.GameClient;
import com.benkyou.client.systems.ImagingSystem;
import com.benkyou.common.messages.VNCMessage;
import com.benkyou.util.ByteArrayList;
import com.jme3.texture.Image;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import jme3tools.converters.ImageToAwt;

/**
 *
 * @author Austin Allman
 */
public class VNCListener implements MessageListener<Client> {

    private GameClient gameClient;
    private ByteArrayList bal;
    private int currentImage;
    private int numberOfParts;
    private int lastReadImage;
    private ByteBuffer byteBuffer;
    private BufferedImage desktopImage;
    private boolean firstRun = true;
    private static BufferedImage decodedImage;

    /**
     * 
     * @param gameClient
     */
    public VNCListener(GameClient gameClient) {
        this.gameClient = gameClient;
        currentImage = -1;
        numberOfParts = -1;
        bal = new ByteArrayList();
    }

    /**
     * 
     */
    public void clearImage() {
        currentImage = -1;
        numberOfParts = -1;
        lastReadImage = -1;
        bal.clearArrayList();
    }

    /**
     * 
     * @param argsp
     */
    public static void main(String argsp[]) {
    }
    int counter = 0;

    /**
     * 
     * @param source
     * @param m
     */
    public void messageReceived(Client source, Message m) {
        if (m instanceof VNCMessage) {
            VNCMessage vncMessage = (VNCMessage) m;
            if (gameClient.isUp()) {
                processImages(vncMessage);
            }
        }
    }

    private Image convertToJme(BufferedImage desktopImage) {
        if (firstRun) {
            byteBuffer = ByteBuffer.allocateDirect((desktopImage.getHeight() * desktopImage.getWidth() * 4));
            firstRun = false;
        }
        byteBuffer.clear();
        ImageToAwt.convert(desktopImage, ImagingSystem.jmeformat, byteBuffer);
        Image im = new Image(ImagingSystem.jmeformat, desktopImage.getWidth(), desktopImage.getHeight(), byteBuffer.duplicate(), null);
        return im;
    }

    /**
     * 
     * @param bytesToDecode
     * @return
     * @throws IOException
     */
    public BufferedImage decodeStream(byte[] bytesToDecode) throws IOException {
        ByteArrayInputStream is = new ByteArrayInputStream(bytesToDecode);
        JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(is);
        decodedImage = decoder.decodeAsBufferedImage();
        return decodedImage;
    }

    private void processImages(VNCMessage vncMessage) {
        if (vncMessage.getImageNumber() == 0 && currentImage == -1) {
            currentImage = vncMessage.getImageID();
            numberOfParts = vncMessage.getNumberOfParts() - 1;
            lastReadImage = vncMessage.getImageNumber();
            bal.addBytes(vncMessage.getImageData());
        } else if (vncMessage.getImageID() == currentImage) {
            lastReadImage++;
            if (vncMessage.getImageNumber() != lastReadImage) {
                clearImage();
            } else if (vncMessage.getImageNumber() == numberOfParts) {
                bal.addBytes(vncMessage.getImageData());
                try {
                    // implement the decode method desktopImage =  TightVNCImageByteStream.decodeStream(bal.getByteArray());
                    desktopImage = decodeStream(bal.getByteArray());
                    Image jmeImage = convertToJme(desktopImage);//getImagingSystemByType("vnc").getImageToProject());//.setImage(convertToJme(desktopImage));
                    gameClient.getVNCImagingSystem().getImageToProject().setImage(jmeImage);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                clearImage();
            } else {
                bal.addBytes(vncMessage.getImageData());
            }
        } else {
            clearImage();
        }
    }
}
